	export default {
		name: 'kzhedit',
		props: {
		    option: Object,
			modelValue: {
				type: Array,
				default: () => [{
					type: 'text',
					value: '',
					f: false
				}]
			}
		},
		emits: ['update:modelValue'],
		setup(props, {emit}) {
		    const isInternalUpdate = ref(false); //内部更新标记
            const historyStack = ref([JSON.stringify(props.modelValue)])
            const currentStep = ref(0);
            const baseurl = window.APP_CONFIG.baseurl;
            const gjc = ref();
            const pollId = ref(null); // 修改为null初始化
            const isAIDialogVisible = ref(false)
            const aiPrompt = ref('')
            const isAIGenerating = ref(false)
            const focusedIndex = ref(-1);
            const videoParseDialogVisible = ref(false);
            const videoUrl = ref('');
            const isParsing = ref(false);
            
            onMounted(() => {
                window.addEventListener('keydown', (e) => {
                    if (e.ctrlKey && e.key === 'z') {
                        e.preventDefault()
                        undo()
                    }
                    if (e.ctrlKey && e.key === 'y') {
                        e.preventDefault()
                        redo()
                    }
                })
            })
            
            const showAIDialog = () => {
                aiPrompt.value = ''
                isAIDialogVisible.value = true
            }
            
			// 历史管理逻辑
            const saveHistory = _.debounce(() => {
                const currentState = JSON.stringify(props.modelValue)
                if (currentState === historyStack.value[currentStep.value]) return
                historyStack.value = historyStack.value.slice(0, currentStep.value + 1)
                historyStack.value.push(currentState)
                currentStep.value++
                if (historyStack.value.length > 100) {
                    historyStack.value.shift()
                    currentStep.value = Math.max(currentStep.value - 1, 0)
                }
            }, 300, { leading: false, trailing: true });
            
            // 文本块更新
            const updateBlockValue = (index, value) => {
                const newBlocks = props.modelValue.map((block, i) => i === index ? { ...block, value } : block);
                isInternalUpdate.value = true  // 标记内部更新
                emit('update:modelValue', newBlocks)
                saveHistory()
            }

			// 撤销/重做
			const undo = () => {
				if (currentStep.value > 0) {
					currentStep.value--
					const snapshot = JSON.parse(historyStack.value[currentStep.value]);
					isInternalUpdate.value = true;
					emit('update:modelValue', cloneDeep(snapshot))
				}
			}

			const redo = () => {
				if (currentStep.value < historyStack.value.length - 1) {
					currentStep.value++
					const snapshot = JSON.parse(historyStack.value[currentStep.value]);
					isInternalUpdate.value = true;
					emit('update:modelValue', cloneDeep(snapshot))
				}
			}

			// 内容操作
			const addTextBlock = () => {
				const newBlocks = [...props.modelValue, {f: false, type: 'text',value: ''}];
				isInternalUpdate.value = true;
				emit('update:modelValue', newBlocks);
				saveHistory();
			}

            // 处理上传成功
            const handleMediaUpload = (type, response) => {
                if (response.code !== 0) {
                    return ElMessage.error(response.message || '上传失败');
                }
                const newBlocks = [...props.modelValue, {f: false, type: type, value: response.data}];
                isInternalUpdate.value = true;
                emit('update:modelValue', newBlocks);
                saveHistory();
            }

			// 文件类型校验
			const checkFileType = (expectedType) => {
				return (file) => {
					const typeMatch = file.type.match(/(image|video)\//);
					const actualType = typeMatch ? typeMatch[1] : '';
					if (actualType !== expectedType) {
						ElMessage.error(`请选择正确的${expectedType === 'image' ? '图片' : '视频'}文件`);
						return false
					}
					const maxSize = expectedType === 'image' ? 5 * 1024 * 1024 : 100 * 1024 * 1024;
					if (file.size > maxSize) {
						ElMessage.error(`文件大小不能超过${maxSize/1024/1024}MB`);
						return false
					}
					return true
				}
			}

			const removeBlock = (index) => {
				const newBlocks = props.modelValue.filter((_, i) => i !== index);
				isInternalUpdate.value = true;
				emit('update:modelValue', newBlocks.length ? newBlocks : [{
					type: 'text',
					value: ''
				}])
				saveHistory()
			}

			const moveBlockUp = (index) => {
				if (index === 0) return
				const newBlocks = [...props.modelValue];
				[newBlocks[index], newBlocks[index - 1]] = [newBlocks[index - 1], newBlocks[index]]
				isInternalUpdate.value = true;
				emit('update:modelValue', newBlocks)
				saveHistory()
			}

			const moveBlockDown = (index) => {
				if (index === props.modelValue.length - 1) return
				const newBlocks = [...props.modelValue];
				[newBlocks[index], newBlocks[index + 1]] = [newBlocks[index + 1], newBlocks[index]]
				isInternalUpdate.value = true;
				emit('update:modelValue', newBlocks)
				saveHistory()
			}

			const clearContent = () => {
			    isInternalUpdate.value = true;
				emit('update:modelValue', [{
					type: 'text',
					value: ''
				}])
				saveHistory()
			}
			
			//markdown转html数组
            const convertMarkdownToArray = (txt) => {
                const result = [];
                const lines = txt.split('\n');
                let currentText = '';
                for (const line of lines) {
                    const trimmedLine = line.trim();
                    // 直接跳过空行和分隔线（如---、***）
                    if (trimmedLine === '' || trimmedLine.match(/^[-*_]{3,}$/)) {
                        // 如果遇到空行且有未提交的文本，提交段落
                        if (currentText) {
                            result.push({ type: 'text', value: currentText });
                            currentText = '';
                        }
                        continue;
                    }
                    // 处理图片
                    const imgMatch = trimmedLine.match(/!\[.*?\]\((.*?)\)/);
                    if (imgMatch) {
                        if (currentText) {
                            result.push({ type: 'text', value: currentText });
                            currentText = '';
                        }
                        result.push({ type: 'img', value: imgMatch[1] });
                        continue;
                    }
                    // 处理标题（支持h1-h6）
                    const headingMatch = trimmedLine.match(/^(#+)\s*(.*)/);
                    if (headingMatch) {
                        if (currentText) {
                            result.push({ type: 'text', value: currentText });
                            currentText = '';
                        }
                        let value = headingMatch[2]
                        .replace(/^[-]+\s*/, '')            // 移除行首的短横线（如 `-`、`--`）及其后的空格
                        .replace(/^\d+\.\s*/, '')           // 移除开头的 "1. "、"2. " 等编号
                        .replace(/\*\*(.*?)\*\*/g, '$1')    // 去除加粗
                        .replace(/\*(.*?)\*/g, '$1')        // 去除斜体
                        .replace(/\[(.*?)\]\(.*?\)/g, '$1');// 去除链接
                        result.push({ type: 'text', value: value });
                        continue;
                    }
                    // 合并文本段落
                    if (trimmedLine) {
                        currentText += (currentText ? ' ' : '') + trimmedLine
                        .replace(/^[-]+\s*/, '')            // 移除行首的短横线（如 `-`、`--`）及其后的空格
                        .replace(/\[(.*?)\]\(.*?\)/g, '$1')  // 去除链接
                        .replace(/\*\*(.*?)\*\*/g, '$1')     // 去除加粗
                        .replace(/\*(.*?)\*/g, '$1');        // 去除斜体
                    } else if (currentText) {
                        result.push({ type: 'text', value: currentText });
                        currentText = '';
                    }
                }
                if (currentText) result.push({ type: 'text', value: currentText });
                return result;
            };
			
            // 插入到编辑器中
			const insertArticleContent = async (articleData) => {
				const newContent = []
				for (const content of articleData) {
					if (content.type === 'text') {
						newContent.push({
							type: 'text',
							value: content.value,
							f: false
						})
					} else if (content.type === 'img') {
						newContent.push({
							type: 'img',
							value: content.value
						})
					}
				}
				isInternalUpdate.value = true;
				emit('update:modelValue', newContent)
				saveHistory()
			}
			
            const handleAIGenerate = async () => {
            	if (!aiPrompt.value.trim()) {
            		ElMessage.warning('请输入生成内容的描述')
            		return
            	}
            	try {
            		isAIGenerating.value = true
            		gjc.value = aiPrompt.value;
            		await AIConfirm(aiPrompt.value);
            		isAIDialogVisible.value = false
            	} catch (error) {
            		ElMessage.error(error.message)
            	} finally {
            		isAIGenerating.value = false
            	}
            }
            
			// AI生成文章发后端
			const AIConfirm = async (prompt) => {
				try {
					ElMessage.success('正在生成中...')
					const result = await blogformai({prompt: prompt});
					if (!result.taskId) {
						throw new Error('生成任务创建失败')
					}
					startLongPolling(result.taskId)
				} catch (error) {
					throw new Error(`生成失败: ${error.message}`)
				}
			}

            const startLongPolling = (taskId) => {
                pollId.value = setInterval(async () => {
                    try {
                        const res = await blogformai({prompt: gjc.value, pollId: taskId})
                        if (res.statusCode === 404) {
                            throw new Error('任务已过期');
                        }
                        if (res.completed) {
                            stopLongPolling();
                            const newContent = res.result ? convertMarkdownToArray(res.result) : [...props.modelValue];
                            emit('update:modelValue', newContent);
                            saveHistory();
                        } else {
                            const txt = res.progress || '';
                            const currentBlocks = [...props.modelValue];
                            isInternalUpdate.value = true
                            if (currentBlocks.length > 0 && currentBlocks[currentBlocks.length - 1].type === 'text') {
                                const newBlocks = [...currentBlocks]
                                newBlocks[newBlocks.length - 1] = {
                                    ...newBlocks[newBlocks.length - 1],
                                    value: txt
                                }
                                emit('update:modelValue', newBlocks)
                            } else {
                                emit('update:modelValue', [
                                    ...currentBlocks,
                                    { type: 'text', value: txt, f: false }
                                ])
                            }
                        }
                    } catch (error) {
                        stopLongPolling();
                        ElMessage.error(error.message.includes('404') ? 
                            '生成任务已超时' : error.message)
                    }
                }, 1500)
            }

			const stopLongPolling = () => {
				clearInterval(pollId.value);
				pollId.value = null;
			}
			
			const cloneDeep = (data) => {
			    return JSON.parse(JSON.stringify(data));
			}
			
            // 新增URL提取正则表达式
            const extractValidUrl = (input) => {
                // 优化后的正则表达式（修正特殊字符转义）
                const urlRegex = /(https?:\/\/[^\s<>{}|\\^[\]"]*[^\s<>{}|\\^[\]",.!?:;'`\)\]])/gi;
                const matches = input.match(urlRegex) || [];
                const supportedDomains = [
                    'douyin.com', 'iesdouyin.com', 
                    'kuaishou.com', 'chenzhongtech.com',
                    'bilibili.com', 'b23.tv',
                    'youtube.com', 'youtu.be'
                ];
                return matches.filter(url => {
                    try {
                        const urlObj = new URL(url);
                        // 使用endsWith更精确匹配域名
                        return supportedDomains.some(domain => 
                            urlObj.hostname.endsWith(domain) // 修正括号闭合
                        );
                    } catch {
                        return false;
                    }
                });
            };
			
            // 视频解析方法
            const handleVideoParse = async () => {
                const rawInput = videoUrl.value.trim();
                if (!rawInput) {
                    return ElMessage.warning('请输入视频链接');
                }
            
                try {
                    const urls = extractValidUrl(rawInput);
                    if (urls.length === 0) throw new Error('未检测到有效链接');
                    if (urls.length > 1) throw new Error('请每次只提交一个链接');
                    const cleanedUrl = urls[0].replace(/[.,;?!)]+$/g, '');
                    const encodedUrl = encodeURI(cleanedUrl);
                    const loading = ElLoading.service({
                        lock: true,
                        text: '视频解析中（可能需要1-3分钟，请勿关闭页面）',
                        background: 'rgba(0, 0, 0, 0.7)',
                    });
                    try {
                        isParsing.value = true;
                        const response = await parseVideoUrlApi({ url: encodedUrl });
                        if (!response.url) {
                            throw new Error(response.message || '解析失败');
                        }
                        // 分块更新显示
                        const newBlocks = [...props.modelValue];
                        newBlocks.push({type: 'video', value: response.url, f: false});
                        isInternalUpdate.value = true;
                        emit('update:modelValue', newBlocks);
                        saveHistory();
                        videoParseDialogVisible.value = false;
                        videoUrl.value = '';
                        ElMessage.success('视频解析成功');
                    } finally {
                        loading.close();
                    }
                } catch (error) {
                    ElMessage.error(`解析失败: ${error.message}`);
                    console.error('Video parse error:', error);
                    // 自动重试提示
                    if (error.message.includes('timeout')) {
                        ElMessageBox.confirm('视频下载超时，是否重试？', '提示', {
                            confirmButtonText: '重试',
                            cancelButtonText: '取消',
                            type: 'warning'
                        }).then(() => {
                            handleVideoParse();
                        });
                    }
                } finally {
                    isParsing.value = false;
                }
            };

			// 监听外部变化
            watch(() => props.modelValue, (newVal) => {
                if (isInternalUpdate.value) {
                    isInternalUpdate.value = false
                    return
                }
                // 仅处理真正来自外部的更新
                const currentState = JSON.stringify(newVal)
                historyStack.value = [currentState]
                currentStep.value = 0
            }, { deep: true })

			return {
				historyStack,
				currentStep,
				focusedIndex,
				addTextBlock,
				updateBlockValue,
				removeBlock,
				undo,
				redo,
				moveBlockUp,
				moveBlockDown,
				clearContent,
				convertMarkdownToArray,
				insertArticleContent,
				AIConfirm,
				startLongPolling,
				stopLongPolling,
				gjc,
				baseurl,
                isAIDialogVisible,
                aiPrompt,
                isAIGenerating,
                showAIDialog,
                handleAIGenerate,
                saveHistory,
                isInternalUpdate,
                checkFileType,
                handleMediaUpload,
                videoParseDialogVisible, videoUrl, isParsing, handleVideoParse, extractValidUrl
			}
		},
		
    template: `
	<div class="editor-container">
		<!-- AI生成弹窗 -->
		<el-dialog v-model="isAIDialogVisible" title="AI内容生成" width="500px" :close-on-click-modal="false">
			<el-input v-model="aiPrompt" type="textarea" :rows="4" placeholder="请输入生成内容的描述（例如：写一篇关于人工智能的科普文章）" />
			<template #footer>
				<div class="dialog-footer">
					<el-button @click="isAIDialogVisible = false">取消</el-button>
					<el-button type="primary" :loading="isAIGenerating" @click="handleAIGenerate">
						{{ isAIGenerating ? '生成中...' : '开始生成' }}
					</el-button>
				</div>
			</template>
		</el-dialog>
		
        <!-- 视频解析弹窗 -->
        <el-dialog v-model="videoParseDialogVisible" title="视频链接解析" width="500px" :close-on-click-modal="false">
            <el-input v-model="videoUrl" placeholder="请输入视频链接（支持抖音、快手等平台）" clearable @keyup.enter="handleVideoParse">
                <template #append>
                    <el-button :loading="isParsing" @click="handleVideoParse">解析</el-button>
                </template>
            </el-input>
        </el-dialog>
	
		<div class="blocks-container">
			<div v-for="(block, index) in modelValue" :key="index" :class="{ focused: focusedIndex === index }" class="block-container">
				<!-- 文本区块 -->
				<div v-if="block.type === 'text'" class="media-block">
					<el-input v-model="block.value" type="textarea" :autosize="{ minRows: 2 }" @focus="focusedIndex = index"
						@blur="saveHistory" @update:model-value="val => updateBlockValue(index, val)" />
				</div>

				<!-- 图片区块 -->
				<div v-if="block.type === 'img'" class="media-block">
					<el-image :src="block.value" fit="contain" class="image-preview">
						<template #error>
							<div class="image-error">图片加载失败</div>
						</template>
					</el-image>
				</div>

				<!-- 视频区块 -->
				<div v-if="block.type === 'video'" class="media-block">
					<video @longpress="moveBlockDown(index)" :src="block.value" class="media-video" controls />
				</div>

				<!-- 操作按钮区 -->
				<div class="block-actions">
					<el-button type="danger" icon="Delete" @click="removeBlock(index)" />
					<el-button @click="moveBlockUp(index)" :disabled="index === 0">
						<el-icon><Top /></el-icon>
					</el-button>
					<el-button @click="moveBlockDown(index)" :disabled="index === modelValue.length - 1">
						<el-icon><Bottom /></el-icon>
					</el-button>
				</div>
			</div>
		</div>

		<!-- 工具栏 -->
		<div class="toolbar">
            <el-button-group class="main-actions">
                <el-button @click="addTextBlock" class="history-btn"><el-icon><DocumentAdd /></el-icon> 添加文字</el-button>
                
                <!-- 图片上传 -->
                <el-upload :show-file-list="false" :action="baseurl + 'v1/upload'" :data="option" :on-success="(res, file) => handleMediaUpload('img', res, file)" :before-upload="() => checkFileType('image')" accept=".jpg, .jpeg, .png">
                	<el-button class="history-btn"><el-icon><Picture /></el-icon> 添加图片</el-button>
                </el-upload>
                
                <!-- 视频上传 -->
                <el-upload :show-file-list="false" :action="baseurl + 'v1/uploadvideo'" :data="option" :on-success="(res, file) => handleMediaUpload('video', res, file)" :before-upload="() => checkFileType('video')" accept=".mp4">
                	<el-button class="history-btn"><el-icon><VideoCamera /></el-icon> 添加视频</el-button>
                </el-upload>
                
                <el-button @click="videoParseDialogVisible = true" class="history-btn"><el-icon><Link /></el-icon> 解析视频</el-button>
                
                <el-button @click="showAIDialog" class="history-btn"><el-icon><MagicStick /></el-icon> AI生成</el-button>
            </el-button-group>

			<div class="history-actions">
				<el-button-group>
					<el-button :disabled="currentStep === 0" @click="undo" class="history-btn">
						<el-icon><RefreshLeft /></el-icon> 撤销
					</el-button>
					<el-button :disabled="currentStep === historyStack.length - 1" @click="redo" class="history-btn">
						<el-icon><RefreshRight /></el-icon> 重做
					</el-button>
				</el-button-group>
				
				<el-button type="danger" @click="clearContent" class="clear-btn">
					<el-icon><Delete /></el-icon> 清空
				</el-button>
			</div>
		</div>
	</div>
    `
}